/**
 *
 */
package com.honeybees.web.captcha.service.impl;

import java.awt.Color;
import java.io.OutputStream;
import java.util.Random;

import javax.annotation.Resource;

import org.patchca.color.ColorFactory;
import org.patchca.filter.predefined.DoubleRippleFilterFactory;
import org.patchca.filter.predefined.WobbleRippleFilterFactory;
import org.patchca.font.FontFactory;
import org.patchca.font.RandomFontFactory;
import org.patchca.service.ConfigurableCaptchaService;
import org.patchca.utils.encoder.EncoderHelper;
import org.patchca.word.RandomWordFactory;
import org.springframework.stereotype.Service;

import com.honeybees.web.captcha.cache.CaptchaCacheHandler;
import com.honeybees.web.captcha.patchca.background.CustomBackgroundFactory;
import com.honeybees.web.captcha.patchca.background.NoLineBackgroundFactory;
import com.honeybees.web.captcha.service.CaptchaService;

/**
 * <dl>
 * <dt><b> 验证码 </b></dt>
 * <p>
 * <dd>功能描述</dd>
 * </dl>
 * <p>
 * Copyright (C) All rights reserved.
 * </p>
 *
 * @author 李远明
 * @version 2016-05-27 11:08:51
 */
@Service
public class CaptchaServiceImpl implements CaptchaService {

    private static final int FONT_SIZE = 33;
    private static final String[] FONT_FAMILY = {"Blocked In", "Pintav?re", "Engravers MT", "BARNACLE", "Colonna MT"};

    private static final int WIDTH = 120; // 100
    private static final int HEIGHT = 40; // 45

    private static Random random = new Random();

    @Resource
    private CustomBackgroundFactory customBackgroundFactory;

    @Resource
    private NoLineBackgroundFactory noLineBackgroundFactory;

    @Resource
    private CaptchaCacheHandler cacheHandler;

    private static ConfigurableCaptchaService cs = null;

    /**
     * {@inheritDoc}
     *
     * @author 李远明
     * @version 2016-05-27 11:08:51
     */
    @Override
    public void createCaptchaImage(String sessionId, OutputStream out) throws Exception {
        ConfigurableCaptchaService captchaService = getService();

        captchaService.setWidth(WIDTH);
        captchaService.setHeight(HEIGHT);

        boolean noLine = false;
        int i = random.nextInt(5);
        switch (i) {
            case 0:
                captchaService.setFilterFactory(new DoubleRippleFilterFactory());
                break;
            case 1:
                captchaService.setFilterFactory(new DoubleRippleFilterFactory());
                break;
            case 2:
                captchaService.setFilterFactory(new DoubleRippleFilterFactory());
                break;
            case 3:
                captchaService.setFilterFactory(new WobbleRippleFilterFactory());
                break;
            case 4:
                captchaService.setFilterFactory(new WobbleRippleFilterFactory());
        }

        noLine = (i % 2) == 0;
        if (noLine) {
            captchaService.setBackgroundFactory(noLineBackgroundFactory);
        } else {
            captchaService.setBackgroundFactory(customBackgroundFactory);
        }

        String token = EncoderHelper.getChallangeAndWriteImage(captchaService, "png", out);
        cacheHandler.saveCaptchaCode(sessionId, token);
    }

    public static ConfigurableCaptchaService getService() {
        if (cs != null)
            return cs;

        ColorFactory cf = new ColorFactory() {
            public Color getColor(int x) {
                int[] c = new int[3];
                int i = random.nextInt(c.length);
                for (int y = 0; y < c.length; y++) {
                    if (y == i) {
                        c[y] = random.nextInt(71);
                    } else {
                        c[y] = random.nextInt(256);
                    }
                }
                return new Color(c[0], c[1], c[2]);
            }
        };
        cs = new ConfigurableCaptchaService();
        cs.setColorFactory(cf);

        RandomWordFactory wf = new RandomWordFactory();
        wf.setCharacters("2345678abcdefhkmnpqrstuvwxyzABCDEFGHGKMNPRSTUVWXYZ");
        wf.setMaxLength(4);
        wf.setMinLength(4);
        cs.setWordFactory(wf);

        FontFactory ff = new RandomFontFactory(FONT_SIZE, FONT_FAMILY);
        cs.setFontFactory(ff);
        return cs;
    }

}
